﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Logging;
using NuGet.Packaging;
using ShareYou.CacheMemory;
using ShareYou.Configuration;
using ShareYou.Entity.Module.Dto;
using ShareYou.Entity.UserInfo;
using ShareYou.EntityFramework.ShareYouDb;
using ShareYou.ICache;
using ShareYou.IExtensions;
using ShareYou.IServices.Module;
using ShareYou.Services.Module;
using ShareYou.Tools.ReflectExtension;
using AspNetCore.Identity.EntityFramework6;

namespace ShareYou
{
    public class Startup
    {
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();

            if (env.IsDevelopment())
            {
                // This will push telemetry data through Application Insights pipeline faster, allowing you to view results immediately.
                builder.AddApplicationInsightsSettings(developerMode: true);
            }
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; }

        /// <summary>
        /// 模块程序集
        /// </summary>
        public IList<ModuleAssemblyInfo> Assemblys { get; set; }

        //配置服务 This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            #region 配置数据库服务
            services.AddSingleton<SyDbContext>(
                _ => new SyDbContext(Configuration.GetSection("ConnectionStrings:ShareYouDb-Dev").Value));

            
            #endregion

            #region 主程序初始化操作
            IHostingEnvironment env = services.BuildServiceProvider().GetService<IHostingEnvironment>();
            //主程序服务注入
            services.AddSingleton(typeof(ICacheManager), typeof(CacheForMemory));
            services.AddSingleton(typeof(IModuleInfoService), typeof(ModuleInfoService));

            //配置Razor视图引擎定位
            services.ConfigRazorViewPath();

            // Add framework services.
            services.AddApplicationInsightsTelemetry(Configuration);
            #endregion
            //加载所有的模块程序集
            this.Assemblys = services.LoadModules(Path.Combine(env.ContentRootPath, "Modules"));

            //加载Controller依赖服务
            IList<IModuleServicesConfig> modelServices = new List<IModuleServicesConfig>();
            IList<IModuleInfo> moduleInfos = new List<IModuleInfo>();
            foreach (var moduleAssembly in this.Assemblys)
            {
                modelServices.AddRange(ReflectHelper.GetClasses<IModuleServicesConfig>(moduleAssembly.Assembly));
                moduleInfos.AddRange(ReflectHelper.GetClasses<IModuleInfo>(moduleAssembly.Assembly));
            }
            //注册模块服务
            services.RegisterModuleService(env, modelServices);
            //保存模块信息
            services.SaveModuleInfo(moduleInfos);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseApplicationInsightsRequestTelemetry();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseApplicationInsightsExceptionTelemetry();
            app.UseStaticFiles(); //主程序静态文件系统
            //静态文件系统,包括那些模块的静态文件(统一放入wwwroot文件夹中)
            foreach (var moduleAssembly in Assemblys)
            {
                var wwwrootPath = Path.Combine(moduleAssembly.FolderPath, "wwwroot");
                if (Directory.Exists(wwwrootPath))
                {
                    //如果存在则应用系统
                    app.UseStaticFiles(new StaticFileOptions()
                    {
                        FileProvider = new PhysicalFileProvider(wwwrootPath),
                        RequestPath = new PathString("/"+moduleAssembly.FolderName.Split('.')[2])
                    });
                }
            }
            //加载主程序和模块的路由
            IList<IModuleRouteConfig> routeConfigList = new List<IModuleRouteConfig>();
            foreach (var moduleAssmebly in this.Assemblys)
            {
                routeConfigList.AddRange(ReflectHelper.GetClasses<IModuleRouteConfig>(moduleAssmebly.Assembly));
            }
            app.ConfigModuleRoute(routeConfigList);
            //MvcServiceCollectionExtensions
        }
    }
}
